import { createParamDecorator, ExecutionContext } from '@nestjs/common'
import { Request } from 'express'

/**
 * 用户信息接口
 */
export interface UserInfo {
  id: string
  username: string
  email: string
  role: string
  permissions?: string[]
  avatar?: string
  nickname?: string
  status: string
  createdAt: Date
  updatedAt: Date
}

/**
 * 当前用户装饰器
 * 用于获取当前登录用户的完整信息
 *
 * @example
 * ```typescript
 * @Get('profile')
 * getProfile(@CurrentUser() user: UserInfo) {
 *   return user;
 * }
 * ```
 */
export const CurrentUser = createParamDecorator(
  (data: keyof UserInfo | undefined, ctx: ExecutionContext): UserInfo | any => {
    const request = ctx.switchToHttp().getRequest<Request>()
    const user = request.user as UserInfo

    if (!user) {
      return null
    }

    // 如果指定了特定字段，只返回该字段
    if (data) {
      return user[data]
    }

    // 返回完整用户信息，但排除敏感信息
    const { ...safeUser } = user
    return safeUser
  }
)

/**
 * 用户ID装饰器
 * 用于快速获取当前用户ID
 *
 * @example
 * ```typescript
 * @Get('my-articles')
 * getMyArticles(@UserId() userId: string) {
 *   return this.articleService.findByUserId(userId);
 * }
 * ```
 */
export const UserId = createParamDecorator((data: unknown, ctx: ExecutionContext): string => {
  const request = ctx.switchToHttp().getRequest<Request>()
  const user = request.user as UserInfo
  return user?.id
})

/**
 * 用户角色装饰器
 * 用于快速获取当前用户角色
 *
 * @example
 * ```typescript
 * @Get('role-specific')
 * getRoleSpecificData(@UserRole() role: string) {
 *   return this.service.getDataByRole(role);
 * }
 * ```
 */
export const UserRole = createParamDecorator((data: unknown, ctx: ExecutionContext): string => {
  const request = ctx.switchToHttp().getRequest<Request>()
  const user = request.user as UserInfo
  return user?.role
})

/**
 * 用户权限装饰器
 * 用于快速获取当前用户权限列表
 *
 * @example
 * ```typescript
 * @Get('permissions')
 * getUserPermissions(@UserPermissions() permissions: string[]) {
 *   return { permissions };
 * }
 * ```
 */
export const UserPermissions = createParamDecorator((data: unknown, ctx: ExecutionContext): string[] => {
  const request = ctx.switchToHttp().getRequest<Request>()
  const user = request.user as UserInfo
  return user?.permissions || []
})

/**
 * 用户邮箱装饰器
 * 用于快速获取当前用户邮箱
 *
 * @example
 * ```typescript
 * @Post('send-notification')
 * sendNotification(@UserEmail() email: string) {
 *   return this.notificationService.sendToEmail(email);
 * }
 * ```
 */
export const UserEmail = createParamDecorator((data: unknown, ctx: ExecutionContext): string => {
  const request = ctx.switchToHttp().getRequest<Request>()
  const user = request.user as UserInfo
  return user?.email
})

/**
 * 用户名装饰器
 * 用于快速获取当前用户名
 *
 * @example
 * ```typescript
 * @Get('welcome')
 * getWelcomeMessage(@Username() username: string) {
 *   return { message: `Welcome, ${username}!` };
 * }
 * ```
 */
export const Username = createParamDecorator((data: unknown, ctx: ExecutionContext): string => {
  const request = ctx.switchToHttp().getRequest<Request>()
  const user = request.user as UserInfo
  return user?.username
})

/**
 * 用户昵称装饰器
 * 用于快速获取当前用户昵称
 *
 * @example
 * ```typescript
 * @Get('profile')
 * getProfile(@UserNickname() nickname: string) {
 *   return { nickname };
 * }
 * ```
 */
export const UserNickname = createParamDecorator((data: unknown, ctx: ExecutionContext): string => {
  const request = ctx.switchToHttp().getRequest<Request>()
  const user = request.user as UserInfo
  return user?.nickname || user?.username
})

/**
 * 用户头像装饰器
 * 用于快速获取当前用户头像URL
 *
 * @example
 * ```typescript
 * @Get('avatar')
 * getAvatar(@UserAvatar() avatar: string) {
 *   return { avatar };
 * }
 * ```
 */
export const UserAvatar = createParamDecorator((data: unknown, ctx: ExecutionContext): string => {
  const request = ctx.switchToHttp().getRequest<Request>()
  const user = request.user as UserInfo
  return user?.avatar
})

/**
 * 用户状态装饰器
 * 用于快速获取当前用户状态
 *
 * @example
 * ```typescript
 * @Get('status')
 * getUserStatus(@UserStatus() status: string) {
 *   return { status };
 * }
 * ```
 */
export const UserStatus = createParamDecorator((data: unknown, ctx: ExecutionContext): string => {
  const request = ctx.switchToHttp().getRequest<Request>()
  const user = request.user as UserInfo
  return user?.status
})

/**
 * 可选用户装饰器
 * 用于获取可能存在的用户信息（不强制要求登录）
 *
 * @example
 * ```typescript
 * @Get('public-with-user')
 * getPublicData(@OptionalUser() user?: UserInfo) {
 *   if (user) {
 *     return this.service.getPersonalizedData(user.id);
 *   }
 *   return this.service.getPublicData();
 * }
 * ```
 */
export const OptionalUser = createParamDecorator(
  (data: keyof UserInfo | undefined, ctx: ExecutionContext): UserInfo | any | null => {
    const request = ctx.switchToHttp().getRequest<Request>()
    const user = request.user as UserInfo

    if (!user) {
      return null
    }

    // 如果指定了特定字段，只返回该字段
    if (data) {
      return user[data]
    }

    // 返回完整用户信息，但排除敏感信息
    const { ...safeUser } = user
    return safeUser
  }
)

/**
 * 用户信息验证装饰器
 * 用于验证用户是否存在并返回用户信息
 *
 * @example
 * ```typescript
 * @Get('secure')
 * getSecureData(@ValidatedUser() user: UserInfo) {
 *   // 确保用户已登录且信息有效
 *   return this.service.getSecureData(user.id);
 * }
 * ```
 */
export const ValidatedUser = createParamDecorator(
  (data: keyof UserInfo | undefined, ctx: ExecutionContext): UserInfo | any => {
    const request = ctx.switchToHttp().getRequest<Request>()
    const user = request.user as UserInfo

    if (!user || !user.id) {
      throw new Error('用户信息无效或未登录')
    }

    // 检查用户状态
    if (user.status !== 'active') {
      throw new Error('用户账户已被禁用')
    }

    // 如果指定了特定字段，只返回该字段
    if (data) {
      return user[data]
    }

    // 返回完整用户信息，但排除敏感信息
    const { ...safeUser } = user
    return safeUser
  }
)

/**
 * 用户权限检查装饰器
 * 用于检查用户是否具有特定权限
 *
 * @param requiredPermission 需要的权限
 *
 * @example
 * ```typescript
 * @Get('admin-only')
 * getAdminData(@UserWithPermission('admin:read') user: UserInfo) {
 *   return this.service.getAdminData();
 * }
 * ```
 */
export const UserWithPermission = (requiredPermission: string) =>
  createParamDecorator((data: keyof UserInfo | undefined, ctx: ExecutionContext): UserInfo | any => {
    const request = ctx.switchToHttp().getRequest<Request>()
    const user = request.user as UserInfo

    if (!user || !user.id) {
      throw new Error('用户信息无效或未登录')
    }

    // 检查权限
    if (!user.permissions?.includes(requiredPermission)) {
      throw new Error(`用户缺少必要权限: ${requiredPermission}`)
    }

    // 如果指定了特定字段，只返回该字段
    if (data) {
      return user[data]
    }

    // 返回完整用户信息，但排除敏感信息
    const { ...safeUser } = user
    return safeUser
  })()

/**
 * 用户角色检查装饰器
 * 用于检查用户是否具有特定角色
 *
 * @param requiredRoles 需要的角色列表
 *
 * @example
 * ```typescript
 * @Get('editor-only')
 * getEditorData(@UserWithRole(['editor', 'admin']) user: UserInfo) {
 *   return this.service.getEditorData();
 * }
 * ```
 */
export const UserWithRole = (requiredRoles: string[]) =>
  createParamDecorator((data: keyof UserInfo | undefined, ctx: ExecutionContext): UserInfo | any => {
    const request = ctx.switchToHttp().getRequest<Request>()
    const user = request.user as UserInfo

    if (!user || !user.id) {
      throw new Error('用户信息无效或未登录')
    }

    // 检查角色
    if (!requiredRoles.includes(user.role)) {
      throw new Error(`用户角色不符合要求，需要: ${requiredRoles.join(', ')}`)
    }

    // 如果指定了特定字段，只返回该字段
    if (data) {
      return user[data]
    }

    // 返回完整用户信息，但排除敏感信息
    const { ...safeUser } = user
    return safeUser
  })()

/**
 * 请求信息装饰器
 * 用于获取请求相关信息
 */
export class RequestInfo {
  /**
   * 获取客户端IP地址
   */
  static Ip = createParamDecorator((data: unknown, ctx: ExecutionContext): string => {
    const request = ctx.switchToHttp().getRequest<Request>()
    return (
      request.ip ||
      request.connection?.remoteAddress ||
      request.socket?.remoteAddress ||
      (request.headers['x-forwarded-for'] as string)?.split(',')[0] ||
      'unknown'
    )
  })

  /**
   * 获取用户代理信息
   */
  static UserAgent = createParamDecorator((data: unknown, ctx: ExecutionContext): string => {
    const request = ctx.switchToHttp().getRequest<Request>()
    return request.headers['user-agent'] || 'unknown'
  })

  /**
   * 获取请求来源
   */
  static Referer = createParamDecorator((data: unknown, ctx: ExecutionContext): string => {
    const request = ctx.switchToHttp().getRequest<Request>()
    const referer = request.headers.referer || request.headers.referrer
    return Array.isArray(referer) ? referer[0] : referer || 'unknown'
  })

  /**
   * 获取请求ID（如果存在）
   */
  static RequestId = createParamDecorator((data: unknown, ctx: ExecutionContext): string => {
    const request = ctx.switchToHttp().getRequest<Request>()
    return (request as any).requestId || 'unknown'
  })

  /**
   * 获取请求时间戳
   */
  static Timestamp = createParamDecorator((data: unknown, ctx: ExecutionContext): number => {
    return Date.now()
  })
}

/**
 * 用户上下文信息
 */
export interface UserContext {
  user: UserInfo
  ip: string
  userAgent: string
  requestId: string
  timestamp: number
}

/**
 * 用户上下文装饰器
 * 用于获取完整的用户上下文信息
 *
 * @example
 * ```typescript
 * @Post('action')
 * performAction(@UserContext() context: UserContext) {
 *   this.auditService.log(context, 'user_action');
 *   return this.service.performAction(context.user.id);
 * }
 * ```
 */
export const UserContext = createParamDecorator((data: unknown, ctx: ExecutionContext): UserContext => {
  const request = ctx.switchToHttp().getRequest<Request>()
  const user = request.user as UserInfo

  return {
    user,
    ip:
      request.ip ||
      request.connection?.remoteAddress ||
      request.socket?.remoteAddress ||
      (request.headers['x-forwarded-for'] as string)?.split(',')[0] ||
      'unknown',
    userAgent: request.headers['user-agent'] || 'unknown',
    requestId: (request as any).requestId || 'unknown',
    timestamp: Date.now()
  }
})
